package com.cq.hd.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.common.constant.MsgConstant;
import com.cq.hd.common.constant.OrderNoteConstant;
import com.cq.hd.common.entity.mq.NotifyMsgSendDto;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.utils.BeanUtils;
import com.cq.hd.order.api.dto.OrderDto;
import com.cq.hd.order.api.vo.OrderVo;
import com.cq.hd.order.mapper.TbOrderItemMapper;
import com.cq.hd.order.mapper.TbOrderRefundMapper;
import com.cq.hd.order.mq.provider.NotifyMsgProvider;
import com.cq.hd.order.mq.provider.OrderRefundMsgProvider;
import com.cq.hd.order.param.CancelWaitPayOrVerifyOrderParam;
import com.cq.hd.order.param.OrderRefundQueryParam;
import com.cq.hd.order.po.TbOrderItemPo;
import com.cq.hd.order.po.TbOrderPo;
import com.cq.hd.order.po.TbOrderRefundPo;
import com.cq.hd.order.service.OrderStepPriceCashbackService;
import com.cq.hd.order.service.TbOrderItemService;
import com.cq.hd.order.service.TbOrderRefundService;
import com.cq.hd.order.service.TbOrderService;
import com.cq.hd.product.api.TbActiveApi;
import com.cq.hd.product.api.dto.ActiveStepPriceSonDto;
import com.cq.hd.product.api.vo.ActiveVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单退款表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2024-01-17
 */
@Slf4j
@Service
public class TbOrderRefundServiceImpl extends ServiceImpl<TbOrderRefundMapper, TbOrderRefundPo> implements TbOrderRefundService {

    @Lazy
    @Resource
    private TbOrderService orderService;
    @Resource
    private TbOrderItemMapper orderItemMapper;
    @Resource
    private OrderRefundMsgProvider orderRefundMsgProvider;
    @Resource
    private NotifyMsgProvider notifyMsgProvider;
    @Resource
    private TbActiveApi activeApi;
    @Resource
    private OrderStepPriceCashbackService orderStepPriceCashbackService;

    // 阶梯价返现任务
    @Override
    public void scanStepPriceRefundTask() {
        OrderRefundQueryParam orderRefundQueryParam = new OrderRefundQueryParam();
        orderRefundQueryParam.setRefundStates(Collections.singletonList(OrderRefundStateEnum.WAIT.getValue()));
        orderRefundQueryParam.setRefundTypes(Collections.singletonList(RefundTypeEnum.STEP_PRICE.getValue()));
        List<TbOrderRefundPo> orderRefunds = baseMapper.selectListByParam(orderRefundQueryParam);
        if (CollectionUtils.isEmpty(orderRefunds)) {
            return;
        }

        for (TbOrderRefundPo orderRefund : orderRefunds) {
            // 判断订单是否全核销，如果全核销则进行返现打款
            TbOrderPo order = orderService.getById(orderRefund.getOrderId());
            if (OrderStateEnum.VERIFIED.getValue().equals(order.getOrderState())
                    || OrderStateEnum.FINISH.getValue().equals(order.getOrderState())) {
                if (checkOrderAllVerified(order.getId())) {
                    // 返现异步处理逻辑
                    orderRefundMsgProvider.sendMsg(orderRefund.getId());
                    // 返现通知
                    sendCashbackNotification(order, orderRefund.getRefundAmt());
                }
            } else {
                // TODO 如果没有全核销，则判断活动是否结束，如果结束则将钱转给商家
            }
        }
    }

    // 未满员自动退款
    @Override
    public void noFullAutoRefund(Long activeId) {
        ActiveVo activeVo = activeApi.getById(activeId).unpack();
        // 检查是否开启未满自动退
        if (NoFullAutoRefundStateEnum.NO.getValue().equals(activeVo.getNoFullAutoRefundState())) {
            return;
        }
        // 活动最低报名人数要求
        Integer activeMinEnrollNum = getActiveMinEnrollNum(activeVo);
        // 该活动的订单信息
        List<OrderVo> orderList = queryAndFilterValidOrders(activeVo);
        // 人数未满，执行自动退款
        if (orderList.size() < activeMinEnrollNum) {
            for (OrderVo orderVo : orderList) {
                execNoFullRefund(orderVo);
            }
        }
    }

    // 活动结束触发计算阶梯价返现
    @Override
    public void calculateStepPriceRefund(Long activeId) {
        ActiveVo activeVo = activeApi.getById(activeId).unpack();
        // 检查是否开启阶梯价格
        if (StepPriceStateEnum.YES.getValue().equals(activeVo.getStepPriceState())) {
            return;
        }

        List<OrderVo> orderList = queryAndFilterValidOrders(activeVo);
        for (OrderVo orderVo : orderList) {
            orderStepPriceCashbackService.cashbackWhenActiveFull(orderVo.getId(), orderList.size());
        }
    }

    @Override
    public void scanWaitRefundTask() {
        log.info("scanWaitRefundTask start >>>>>>>>>>>>");
        OrderRefundQueryParam orderRefundQueryParam = new OrderRefundQueryParam();
        // 暂时只重试处理拼团的退款
        orderRefundQueryParam.setRefundTypes(Collections.singletonList(RefundTypeEnum.GROUP_FAILED.getValue()));
        orderRefundQueryParam.setRefundStates(Collections.singletonList(OrderRefundStateEnum.WAIT.getValue()));
        List<TbOrderRefundPo> tbOrderRefundPos = baseMapper.selectListByParam(orderRefundQueryParam);
        for (TbOrderRefundPo orderRefund : tbOrderRefundPos) {
            // 返现异步处理逻辑
            log.info("重新投递退款消息：{}", orderRefund.getId());
            orderRefundMsgProvider.sendMsg(orderRefund.getId());
        }
        log.info("scanWaitRefundTask start >>>>>>>>>>>>");
    }

    // 检查是否全部核销，如果子单过期未核销，则不是全核销
    private Boolean checkOrderAllVerified(Long orderId) {
        LambdaQueryWrapper<TbOrderItemPo> qw = Wrappers.<TbOrderItemPo>lambdaQuery()
                .eq(TbOrderItemPo::getOrderId, orderId);
        List<TbOrderItemPo> tbOrderItemPos = orderItemMapper.selectList(qw);
        for (TbOrderItemPo orderItem : tbOrderItemPos) {
            if (Objects.equals(SubOrderStateEnum.EXPIRED.getValue(), orderItem.getSubOrderState())) {
                return false;
            }
        }
        return true;
    }

    private void execNoFullRefund(OrderVo orderVo) {
        if (!orderVo.getOrderState().equals(OrderStateEnum.WAIT_VERIFY.getValue())) {
            return;
        }

        CancelWaitPayOrVerifyOrderParam cancelWaitPayOrVerifyOrderParam = new CancelWaitPayOrVerifyOrderParam();
        BeanUtils.copyProperties(orderVo, cancelWaitPayOrVerifyOrderParam);
        cancelWaitPayOrVerifyOrderParam.setOrgOrderState(OrderStateEnum.WAIT_VERIFY.getValue());
        // 更新订单状态，待核销--》已关闭
        cancelWaitPayOrVerifyOrderParam.setOrderState(OrderStateEnum.CLOSE.getValue());
        cancelWaitPayOrVerifyOrderParam.setOrderNote(OrderNoteConstant.FOUR);
        cancelWaitPayOrVerifyOrderParam.setCloseTime(LocalDateTime.now());
        if (!orderService.cancelWaitPayOrVerifyOrder(cancelWaitPayOrVerifyOrderParam)) {
            log.error("订单未满员退款,修改关闭状态失败, cancelWaitPayOrVerifyOrderParam:{}", JSON.toJSONString(cancelWaitPayOrVerifyOrderParam));
        }
    }

    private List<OrderVo> queryAndFilterValidOrders(ActiveVo activeVo) {
        OrderDto orderParam = new OrderDto();
        orderParam.setActiveIds(Collections.singletonList(activeVo.getId()));
        // 查询待核销、核销中、已核销、待审核的订单
        // 订单取消和关闭可能发生在活动结束时间之后，需要统计在内
        orderParam.setOrderStates(Arrays.asList(OrderStateEnum.WAIT_VERIFY.getValue(), OrderStateEnum.VERIFYING.getValue(), OrderStateEnum.VERIFIED.getValue(),
                OrderStateEnum.WAIT_AUDIT.getValue(), OrderStateEnum.CLOSE.getValue(), OrderStateEnum.CANCEL.getValue()));
        List<OrderVo> orderList = orderService.listByDto(orderParam);

        List<OrderVo> result = new ArrayList<>();
        for (OrderVo orderVo : orderList) {
            if (orderVo.getOrderState().equals(OrderStateEnum.CLOSE.getValue()) && orderVo.getCloseTime().isBefore(activeVo.getEndTime())) {
                continue;
            }
            if (orderVo.getOrderState().equals(OrderStateEnum.CANCEL.getValue()) && orderVo.getCancelTime().isBefore(activeVo.getEndTime())) {
                continue;
            }
            result.add(orderVo);
        }
        return result;
    }

    // 获取活动最低报名人数要求
    private Integer getActiveMinEnrollNum(ActiveVo activeVo) {
        if (StepPriceStateEnum.YES.getValue().equals(activeVo.getStepPriceState())) {
            // 如果开启了，获取阶梯最少人数
            List<ActiveStepPriceSonDto> activeStepPriceVos = activeVo.getActiveStepPrices();
            List<ActiveStepPriceSonDto> sortActiveStepPriceVos = activeStepPriceVos.stream()
                    .sorted(Comparator.comparing(ActiveStepPriceSonDto::getEnrollNum))
                    .collect(Collectors.toList());
            return sortActiveStepPriceVos.get(0).getEnrollNum();
        } else {
            // 如果没开启，获取活动固定人数
            return activeVo.getTotalStock();
        }
    }

    private void sendCashbackNotification(TbOrderPo order, BigDecimal returnAmt) {
        // 发送活动返现系统通知
        NotifyMsgSendDto notifyMsgSendDto = new NotifyMsgSendDto();
        notifyMsgSendDto.setUserId(order.getUserId());
        notifyMsgSendDto.setRoleType(RoleTypeEnum.BUSINESS.getValue());
        notifyMsgSendDto.setMsgType(NotifyMsgTypeEnum.USER_ENROLL_ORDER_RETURN.getValue());
        notifyMsgSendDto.setContent(String.format(MsgConstant.USER_ENROLL_ORDER_RETURN, order.getActiveTitle(), returnAmt));
        notifyMsgSendDto.setMsgState(NotifyMsgStateEnum.NO_READ.getValue());
        notifyMsgProvider.sendMsg(notifyMsgSendDto);
    }

}
